home *** CD-ROM | disk | FTP | other *** search
/ Collection of Internet / Collection of Internet.iso / msdos / lynx / source / wattcp / src / pctcp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-25  |  62.2 KB  |  2,232 lines

  1. /* DEBUG flag may be set for my internal playing */
  2.  
  3. /*
  4. #define DEBUG
  5. */
  6.  
  7. /*
  8.  *  PCTCP - the true worker of Waterloo TCP
  9.  *         - contains all opens, closes, major read/write routines and
  10.  *        basic IP handler for incomming packets
  11.  *      - NOTE: much of the TCP/UDP/IP layering is done at the data structure
  12.  *        level, not in separate routines or tasks
  13.  *
  14.  */
  15.  
  16.  
  17. #include"capalloc.h"
  18. #include"capstdio.h"
  19. #include <copyright.h>
  20. #include <time.h>
  21. #include <stdio.h>
  22. #include <stdarg.h>
  23. #include <stdlib.h>
  24. #include <conio.h>
  25. #include <string.h>
  26. #include <mem.h>
  27. #include <dos.h>
  28. #include <values.h>
  29.  
  30. #include "wattcp.h"
  31. #include "elib.h"
  32.  
  33. static void udp_handler(in_Header *ip);
  34. static udp_write(udp_Socket *s, byte *datap, int len);
  35. static int udp_read(udp_Socket *s, byte *datap, int maxlen);
  36. static void tcp_Retransmitter(void);
  37.  
  38.  
  39. #define TCP_LOCAL 0x4000
  40.  
  41. /* statics */
  42. static tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len);
  43.  
  44. static char far *mono = (char far *)0xb0000000L;
  45. static char far *colour = (char far *)0xb8000000L;
  46.  
  47. static initialized = 0;
  48. static void (*system_yield)() = NULL;
  49. extern int multihomes;
  50. extern word _pktipofs;
  51. void (*_dbugxmit)() = NULL;
  52. void (*_dbugrecv)() = NULL;
  53. void (*wattcpd)() = NULL;
  54.  
  55. char *_hostname = "012345678901234567890123456789012345678901234567890";
  56.  
  57. word _mss = ETH_MSS;
  58.  
  59. char *_wattcp = WATTCP_C;
  60.  
  61. static void tcp_handler(in_Header *ip);
  62. static void udp_handler(in_Header *ip);
  63. extern void icmp_handler(in_Header *ip );
  64.  
  65. static void tcp_unthread(tcp_Socket *ds);
  66. static void tcp_abort(tcp_Socket *s);
  67. void tcp_sendsoon(tcp_Socket *s );
  68. static tcp_send(tcp_Socket *s, int line);
  69. tcp_rst( in_Header *his_ip, tcp_Header *oldtcpp);
  70. static udp_close(udp_Socket *ds);
  71.  
  72.  
  73. /*
  74.  * sock_yield - enable user defined yield function
  75.  */
  76. sock_yield( tcp_Socket *s, void (*fn)())
  77. {
  78.     if ( s )
  79.     s->usr_yield = fn;
  80.     else
  81.     system_yield = fn;
  82.     return( 0 );
  83. }
  84.  
  85. /*
  86.  * sock_mode - set binary or ascii - affects sock_gets, sock_dataready
  87.  *         - set udp checksums
  88.  */
  89. word sock_mode( sock_type *s, word mode )
  90. {
  91.      return( s->tcp.sock_mode = (s->tcp.sock_mode & 0xfffc) | mode);
  92. }
  93.  
  94. /*
  95.  * ip user level timer stuff
  96.  *   void ip_timer_init( void *s, int delayseconds )
  97.  *   int  ip_timer_expired( void *s )
  98.  *    - 0 if not expired
  99.  */
  100. static unsigned long far *realclock = (unsigned long far *)0x000046cL;
  101. #define MAXTICKS 0x1800b0L
  102.  
  103. void ip_timer_init( udp_Socket *s , int delayseconds )
  104. {
  105.     if (delayseconds)
  106.     s->usertimer = set_timeout( delayseconds );
  107.     else
  108.     s->usertimer = 0;
  109. }
  110.  
  111. int ip_timer_expired( udp_Socket *s )
  112. {
  113.     if (! s->usertimer)    /* cannot expire */
  114.     return( 0 );
  115.     return( chk_timeout( s->usertimer));
  116. }
  117. longword MsecClock()
  118. {
  119.     return( (*realclock) * 055L);
  120. }
  121. static long make_timeout( word timeout )
  122. {
  123.     if ( timeout ) return( set_timeout( timeout ));
  124.     return( 0 );
  125. }
  126. /*
  127.  * check_timeout - test agains timeout clock - account for overflow
  128.  */
  129. static int check_timeout( unsigned long timeout )
  130. {
  131.     if (timeout) return( chk_timeout( timeout ));
  132.     return( 0 );
  133. }
  134.  
  135. /*
  136.  * Local IP address
  137.  */
  138. longword my_ip_addr = 0L;    /* for external references */
  139. longword sin_mask = 0xfffffe00L;
  140. longword sin_gate = 0x0;
  141.  
  142.  
  143. /*
  144.  * IP identification numbers
  145.  */
  146.  
  147. static int ip_id = 0;            /* packet number */
  148. static int next_tcp_port = 1024;    /* auto incremented */
  149. static int next_udp_port = 1024;
  150. static tcp_Socket *tcp_allsocs = NULL;
  151. static udp_Socket *udp_allsocs = NULL;
  152.  
  153. /* Timer definitions */
  154. #define RETRAN_STRAT_TIME  1     /* in ticks - how often do we check retransmitter tables*/
  155. #define tcp_RETRANSMITTIME 3     /* interval at which retransmitter is called */
  156. #define tcp_LONGTIMEOUT 31       /* timeout for opens */
  157. #define tcp_TIMEOUT 13           /* timeout during a connection */
  158.  
  159. #ifndef RELEASE
  160. word debug_on = 0;
  161. #endif /* RELEASE */
  162.  
  163. /*
  164.  * look for bugs
  165.  */
  166. tcp_checkfor( tcp_Socket *t )
  167. {
  168.     tcp_Socket *p;
  169.  
  170.     for ( p = tcp_allsocs ; p ; p = p->next )
  171.         if ( p == t ) return( 1 );
  172.     return( 0 );
  173. }
  174.  
  175. /*
  176.  * Shut down the card and all services
  177.  */
  178. void tcp_shutdown()
  179. {
  180.     while (tcp_allsocs)
  181.     tcp_abort( tcp_allsocs );
  182.     _eth_release();
  183.     initialized = 0;
  184. }
  185.  
  186. /*
  187.  * tcp_Init - Initialize the tcp implementation
  188.  *        - may be called more than once without hurting
  189.  */
  190. void tcp_init()
  191. {
  192.     extern int _arp_last_gateway;
  193.     extern int _last_nameserver;
  194.  
  195.     if (!initialized) {
  196.     /* initialize ethernet interface */
  197.     initialized = 1;
  198.     _eth_init();
  199.  
  200.     /* reset the various tables */
  201.     _arp_last_gateway = 0;    /* reset the gateway table */
  202.     _last_nameserver = 0;    /* reset the nameserver table */
  203.     _last_cookie = 0;    /* eat all remaining crumbs */
  204.     *_hostname = 0;        /* reset the host's name */
  205.  
  206.     if (!my_ip_addr) {
  207.         /* using our local reverse ethernet address thingamajig */
  208.         movmem( &_eth_addr[2], &my_ip_addr, 4 );
  209.     }
  210.     _eth_free( 0 );
  211.     next_udp_port = next_tcp_port = 1024 + ((*realclock >> 7 )& 0x1ff);
  212.     }
  213. }
  214.  
  215. /*
  216.  * Checks for bugs when compiling in large model C compiler
  217.  *
  218.  * Borland C uses a 4K stack by default.  In all memory models the
  219.  * stack grows down toward the heap.
  220.  *
  221.  * If you accidentally place tcp_Socket onto the stack (like by making
  222.  * it an automatic variable), then you will have already used up that
  223.  * whole 4K and then some!
  224.  *
  225.  * In large model, this will mess up the data space in a major way
  226.  * because the stack starts at SS:_stklen, or SS:1000, so you will
  227.  * wrap the SP pointer back around to FFFE and start writing over
  228.  * the far heap.  Yuck.
  229.  *
  230.  * In small model it usually doesn't kill your application because
  231.  * you would have to be down to your last 4K of memory and this is
  232.  * not as common.
  233.  *
  234.  * The solutions: declare your sockets as static, or put them on the
  235.  * heap, or bump up your stack size by using the global special variable:
  236.  *
  237.  * unsigned _stklen = 16536;    // set stack to 16 k
  238.  */
  239. static void largecheck( void *s, int size )
  240. {
  241. #ifdef __TURBOC__
  242.     if ( (word)(FP_OFF(s)) > (word)(-size)) {
  243.     outs("ERROR: user stack size error\n");
  244.     sleep(5);
  245.     exit( 3 );
  246.     }
  247. #endif
  248. }
  249.  
  250. /*
  251.  * findfreeport - return unused local port
  252.  *              - oldport = 0:normal port, 1:special port (513-1023)
  253.  *              - we need not be this picky, but it doesn't hurt
  254.  */
  255. static word findfreeport( word oldport )
  256. {
  257.     word temp;
  258.     tcp_Socket *s;
  259.  
  260.     if (( oldport > 0 ) && (oldport < 0xffff))
  261.         return( oldport );
  262.  
  263.     if ( oldport == 0 ) oldport = 1025;
  264.     else oldport = 513;
  265.  
  266.     for ( temp = oldport ; temp < oldport + 510 ; ++temp ) {
  267.         if (( s = (tcp_Socket*)udp_allsocs) != NULL ) {
  268.             while ( s->next && (s->myport != temp))
  269.                 s = (tcp_Socket*)s->next;
  270.             if ( s->myport == temp ) continue;
  271.         }
  272.         if ( (s = tcp_allsocs ) != NULL ) {
  273.             while ( s->next && (s->myport != temp ))
  274.                 s = s->next;
  275.             if ( s->myport == temp ) continue;
  276.         }
  277.         break;
  278.     }
  279.     return( temp );
  280. }
  281.  
  282. /* socket, localport, destaddress */
  283. int udp_open(udp_Socket *s, word lport, longword ina, word port, procref datahandler)
  284. {
  285.     udp_close( s );
  286.     largecheck( s, sizeof( udp_Socket ));
  287.     memset( s, 0, sizeof( udp_Socket ));
  288.     s->rdata = s->rddata;
  289.     s->maxrdatalen = tcp_MaxBufSize;
  290.     s->ip_type = UDP_PROTO;
  291.  
  292.     lport = findfreeport(lport);
  293.  
  294.     s->myport = lport;
  295.     s->myaddr = my_ip_addr;
  296.  
  297.     /* check for broadcast */
  298.     if ( (long)(ina) == -1 || !ina )
  299.     memset( s->hisethaddr, 0xff, sizeof( eth_address ));
  300.     else if ( ! _arp_resolve(ina, (eth_address *) &s->hisethaddr[0], 0) )
  301.     return( 0 );
  302.  
  303.     s->hisaddr = ina;
  304.     s->hisport = port;
  305.     s->dataHandler = datahandler;
  306.     s->usr_yield = system_yield;
  307.     s->safetysig = SAFETYUDP;
  308.     s->next = udp_allsocs;
  309.     udp_allsocs = s;
  310.     return( 1 );
  311. }
  312.  
  313. /*
  314.  * Actively open a TCP connection to a particular destination.
  315.  *    - 0 on error
  316.  */
  317. int tcp_open(tcp_Socket *s, word lport, longword ina, word port, procref datahandler)
  318. {
  319.     largecheck( s, sizeof( tcp_Socket ));   /* stack space warnings */
  320.     tcp_unthread(s);                        /* just in case not totally closed */
  321.  
  322.     memset( s, 0, sizeof( tcp_Socket));
  323.     s->rdata = s->rddata;
  324.     s->maxrdatalen = tcp_MaxBufSize;
  325.     s->ip_type = TCP_PROTO;
  326.     s->mss = _mss;
  327.     s->state = tcp_StateSYNSENT;
  328.     s->timeout = set_timeout( tcp_LONGTIMEOUT );
  329.     s->cwindow = 1;
  330.     s->wwindow = 0;     /* slow start VJ algorithm */
  331.     s->vj_sa = 4;      /* about 250 ms */
  332.     lport = findfreeport( lport );  /* get a nonzero port val */
  333.     s->myaddr = my_ip_addr;
  334.     s->myport = lport;
  335.  
  336.     if ( ina - my_ip_addr <= multihomes ) return( 0 );
  337.     if ( ! _arp_resolve(ina, (eth_address *) &s->hisethaddr[0], 0) )
  338.     return( 0 );
  339.  
  340.     s->hisaddr = ina;
  341.     s->hisport = port;
  342.     s->seqnum = intel( set_timeout( 1 )) & 0xffff0000;
  343.     s->datalen = 0;
  344.     s->flags = tcp_FlagSYN;
  345.     s->unhappy = true;
  346.     s->dataHandler = datahandler;
  347.     s->usr_yield = system_yield;
  348.  
  349.     s->safetysig = SAFETYTCP;       /* insert into chain */
  350.     s->next = tcp_allsocs;
  351.     tcp_allsocs = s;
  352.  
  353.     s->rtt_delay = s->rtt_smooth = 18;    /* one second startup */
  354.     tcp_send(s, __LINE__ );
  355.     s->rtt_time = set_timeout( 1 );
  356.     return( 1 );
  357. }
  358.  
  359. /*
  360.  * Passive open: listen for a connection on a particular port
  361.  */
  362. int tcp_listen(tcp_Socket *s, word lport, longword ina, word port, procref datahandler, word timeout)
  363. {
  364.     largecheck( s, sizeof( tcp_Socket ));
  365.     tcp_unthread(s);                        /* just in case not totally closed */
  366.     memset( s, 0, sizeof( tcp_Socket));
  367.     s->rdata = s->rddata;
  368.     s->maxrdatalen = tcp_MaxBufSize;
  369.     s->ip_type = TCP_PROTO;
  370.     s->mss = _mss;
  371.     s->cwindow = 1;
  372.     s->wwindow = 0;     /* slow start VJ algorithm */
  373.     s->vj_sa = 36;      /* about 250 ms */
  374.  
  375.     s->state = tcp_StateLISTEN;
  376.     if ( !timeout ) s->timeout = 0; /* forever... */
  377.     else s->timeout = set_timeout( timeout );
  378.     lport = findfreeport( lport );  /* get a nonzero port val */
  379.     s->myport = lport;
  380.     s->hisport = port;
  381.     s->hisaddr = ina;
  382.     s->seqnum = intel( (word)(s));
  383.     s->datalen = 0;
  384.     s->flags = 0;
  385.     s->unhappy = false;
  386.     s->dataHandler = datahandler;
  387.     s->usr_yield = system_yield;
  388.  
  389.     s->safetysig = SAFETYTCP;       /* insert into chain */
  390.     s->next = tcp_allsocs;
  391.     tcp_allsocs = s;
  392.  
  393.     return( 1 );
  394. }
  395.  
  396.  
  397. static udp_close(udp_Socket *ds)
  398. {
  399.     udp_Socket *s, **sp;
  400.  
  401.     sp = &udp_allsocs;
  402.     for (;;) {
  403.         s = *sp;
  404.         if ( s == ds ) {
  405.             *sp = s->next;
  406.             break;
  407.         }
  408.     if ( !s ) break;
  409.     if ( ! s->err_msg ) s->err_msg = "UDP Close called";
  410.     sp = &s->next;
  411.     }
  412.     return( 0 );
  413. }
  414.  
  415. /*
  416.  * Send a FIN on a particular port -- only works if it is open
  417.  *   Must still allow receives
  418.  */
  419. static void tcp_close(tcp_Socket *s)
  420. {
  421.     if ( s->ip_type != TCP_PROTO )
  422.     return;
  423.     if ( s->state == tcp_StateESTAB ||
  424.          s->state == tcp_StateESTCL ||
  425.          s->state == tcp_StateSYNREC ) {
  426.  
  427.        if ( s->datalen ) {     /* must first flush all data */
  428.             s->flags |= tcp_FlagPUSH | tcp_FlagACK;
  429.             if ( s->state < tcp_StateESTCL ) {
  430.                 s->state = tcp_StateESTCL;
  431.         tcp_sendsoon( s );
  432.             }
  433.         } else { /* really closing */
  434.             s->flags = tcp_FlagACK | tcp_FlagFIN;
  435.             if (!s->err_msg)
  436.                 s->err_msg = "Connection closed normally";
  437.             s->state = tcp_StateFINWT1;
  438.             s->timeout = set_timeout( 4 ); /* should be a pretty lengthy time */
  439.             tcp_send( s, __LINE__ );
  440.         }
  441.         s->unhappy = true;
  442.     } else if (s->state == tcp_StateCLOSWT ) {
  443.         /* need to ack the fin and get on with it */
  444.         s->state = tcp_StateLASTACK;
  445.         s->flags |= tcp_FlagFIN;
  446.         tcp_send( s, __LINE__ );
  447.         s->unhappy = true;
  448.     }
  449. }
  450.  
  451. /*
  452.  * Abort a tcp connection
  453.  */
  454. static void tcp_abort(tcp_Socket *s)
  455. {
  456.     if (!s->err_msg) s->err_msg = "TCP_ABORT";
  457.     if ( s->state != tcp_StateLISTEN && s->state != tcp_StateCLOSED ) {
  458.         s->flags = tcp_FlagRST  | tcp_FlagACK ;
  459.         s->unhappy = true;
  460.         tcp_send(s, __LINE__);
  461.     }
  462.     s->unhappy = false;
  463.     s->datalen = 0;
  464.     s->ip_type = 0;
  465.     s->state = tcp_StateCLOSED;
  466. /*    if (s->dataHandler) s->dataHandler(s, 0, -1); */
  467.     tcp_unthread(s);
  468. }
  469.  
  470. void sock_abort(tcp_Socket *s )
  471. {
  472.     if ( s->ip_type == TCP_PROTO )
  473.     tcp_abort( s );
  474.     else
  475.         udp_close( (udp_Socket *)s );
  476. }
  477. /*
  478.  * tcp_sendsoon - schedule a transmission pretty soon
  479.  *        - this one has an imperfection at midnight, but it
  480.  *          is not significant to the connection performance
  481.  */
  482. void tcp_sendsoon(tcp_Socket *s )
  483. {
  484.     longword temp;
  485.     if (s->ip_type == TCP_PROTO ) {
  486.     temp = set_ttimeout( 1 );
  487.         if ( temp == s->rtt_time && s->rto < 2 && s->recent == 0 ) {
  488.             s->karn_count = 0;
  489.             tcp_send( s, __LINE__ );
  490.             s->recent = 1;
  491.             return;
  492.         }
  493.         if ((s->unhappy || s->datalen > 0 || s->karn_count == 1)
  494.           && (s->rtt_time < temp ))
  495.             return;
  496.  
  497.         s->rtt_time = set_ttimeout( 1 + (s->rto >> 4) );
  498.     s->karn_count = 1;
  499.     }
  500. }
  501.  
  502. /*
  503.  * Retransmitter - called periodically to perform tcp retransmissions
  504.  */
  505. static longword retran_strat = 0L; /* timeout retran strategy */
  506. static void tcp_Retransmitter(void)
  507. {
  508.     tcp_Socket *s;
  509.  
  510.     /* only do this once per RETRAN_STRAT_TIME milliseconds */
  511.     if ( !chk_timeout( retran_strat ))
  512.     return;
  513.     retran_strat = set_ttimeout( RETRAN_STRAT_TIME );
  514.  
  515.     for ( s = tcp_allsocs; s; s = s->next ) {
  516.         if ( s->datalen > 0 || s->unhappy || s->karn_count == 1 ) {
  517.         /* retransmission strategy */
  518.         if ( chk_timeout( s->rtt_time)) {
  519.  
  520. #ifdef DEBUG
  521. #ifndef RELEASE
  522.     if(debug_on >1) printf("regular retran TO set unacked back to 0 from %u\n", s->unacked);
  523. #endif /* RELEASE */
  524. #endif DEBUG
  525.                 /* strategy handles closed windows   J.D. + E.E. */
  526.                if (s->window == 0 && s->karn_count == 2)
  527.                   s->window = 1;
  528.  
  529.                 if ( s->karn_count == 0 ) {
  530.                     /* if really did timeout */
  531.  
  532.  
  533.                     s->karn_count = 2;
  534.  
  535.                     s->unacked = 0;
  536.                     /* use the backed off rto - implied, no code necessary */
  537.                     /* reduce the transmit window */
  538.                     s->cwindow =  ((s->cwindow + 1) * 3) >> 2;
  539.                     s->wwindow = 0;
  540.                 }
  541.                 if (s->datalen)
  542.                     s->flags |= tcp_FlagPUSH | tcp_FlagACK;
  543.                 tcp_send(s, __LINE__);
  544.         }
  545.     }
  546.         /* handle inactive tcp timeouts */
  547.         if ( sock_inactive && s->inactive_to ) {
  548.             if ( chk_timeout( s->inactive_to)) {
  549.                 /* this baby has timed out */
  550.                 s->err_msg = "Connection timed out - no activity";
  551.                 sock_close( (sock_type *) s );
  552.             }
  553.         }
  554.         if ( s->timeout && chk_timeout( s->timeout)) {
  555.         if ( s->state == tcp_StateTIMEWT ) {
  556.         s->state = tcp_StateCLOSED;
  557.         tcp_unthread(s);
  558.                 break;
  559.             } else if (s->state != tcp_StateESTAB && s->state != tcp_StateESTCL ) {
  560.         s->err_msg = "Timeout, aborting";
  561.         tcp_abort(s);
  562.                 break;
  563.         }
  564.     }
  565.     }
  566.     /* do our various daemons */
  567.     if ( wattcpd ) (*wattcpd)();
  568. }
  569.  
  570.  
  571. /*
  572.  * Unthread a socket from the tcp socket list, if it's there
  573.  */
  574. static void tcp_unthread(tcp_Socket *ds)
  575. {
  576.     tcp_Socket *s, **sp;
  577.  
  578.     if (!ds->rdatalen || (ds->state > tcp_StateESTCL))
  579.         ds->ip_type = 0;                /* fail io */
  580.     ds->state = tcp_StateCLOSED;   /* tcp_tick needs this */
  581.     sp = &tcp_allsocs;
  582.     for (;;) {
  583.     s = *sp;
  584.     if ( s == ds ) {
  585.         *sp = s->next;
  586.             continue;           /* unthread multiple copies if necessary */
  587.     }
  588.     if ( !s ) break;
  589.     sp = &s->next;
  590.     }
  591. }
  592.  
  593. /*
  594.  * tcp_tick - called periodically by user application
  595.  *        - returns 1 when our socket closes
  596.  *        - called with socket parameter or NULL
  597.  */
  598. tcp_tick( sock_type *s )
  599. {
  600.     in_Header *ip;
  601.     static longword timeout = 0;
  602.     static longword start = 0;
  603.  
  604.     int x;
  605.     int packettype;
  606.  
  607.     /* finish off dead sockets */
  608.     if ( s ) {
  609.         if (( s->tcp.ip_type == TCP_PROTO ) &&
  610.             ( s->tcp.state == tcp_StateCLOSED ) &&
  611.             ( s->tcp.rdatalen == 0 )) {
  612.                 tcp_unthread( & s->tcp );
  613.         s->tcp.ip_type = 0;
  614.         }
  615.     }
  616.  
  617.  
  618.     /* plan our next retransmit */
  619.  
  620.     if ( !timeout )
  621.     timeout = make_timeout( tcp_RETRANSMITTIME );
  622.  
  623.     while ( ip = (in_Header *)_eth_arrived( (word *) &packettype ) ) {
  624.     start = *realclock;
  625.  
  626.     switch ( packettype ) {
  627.     case /*0x800*/ 0x008 :
  628.         /* do IP */
  629.         if ( checksum(ip, in_GetHdrlenBytes(ip)) == 0xffff ) {
  630.         switch ( ip->proto ) {
  631.             case TCP_PROTO :
  632.             tcp_handler(ip);
  633.             break;
  634.             case UDP_PROTO :
  635.             udp_handler(ip);
  636.             break;
  637.             case ICMP_PROTO :
  638.             icmp_handler(ip);
  639.             break;
  640.         }
  641.         } else  {
  642. #ifndef RELEASE
  643.         if (debug_on)
  644.             outs("IP Received BAD Checksum \n");
  645. #endif /* RELEASE */
  646.         }
  647.         break;
  648.     case /*0x806*/ 0x608 :
  649.             /* do arp */
  650.         _arp_handler(ip);
  651.         break;
  652.     }
  653.     if (ip) _eth_free(ip);
  654.  
  655.     continue;
  656.     }
  657.     /* check for our outstanding packets */
  658.     tcp_Retransmitter();
  659.  
  660.     return( s->udp.ip_type );
  661. }
  662.  
  663. #ifndef RELEASE
  664. void tcp_set_debug_state( x )
  665. int x;
  666. {
  667.     debug_on = x;
  668. }
  669. #endif /* RELEASE */
  670.  
  671. /* returns 1 if connection is established */
  672. int tcp_established(tcp_Socket *s)
  673. {
  674.     return( s->state >= tcp_StateESTAB );
  675. }
  676.  
  677.  
  678. static udp_write(udp_Socket *s, byte *datap, int len)
  679. {
  680.     tcp_PseudoHeader ph;
  681.     struct _pkt {
  682.     in_Header  in;
  683.     udp_Header udp;
  684.     int       data;
  685. /*    longword maxsegopt; */
  686.     } *pkt;
  687.     byte *dp;
  688.     in_Header *inp;
  689.     udp_Header *udpp;
  690.  
  691.     pkt = (struct _pkt *)_eth_formatpacket(&s->hisethaddr[0], /*0x800*/ 8);
  692.     dp = (byte *) &pkt->data;
  693.     inp = &pkt->in;
  694.     udpp = &pkt->udp;
  695.  
  696.     memset( inp, 0, sizeof( in_Header ));
  697.     inp->length = intel16( sizeof(in_Header) + UDP_LENGTH + len );
  698.  
  699.     /* udp header */
  700.     udpp->srcPort = intel16( s->myport );
  701.     udpp->dstPort = intel16( s->hisport );
  702.     udpp->checksum = 0;
  703.     udpp->length = intel16( UDP_LENGTH + len );
  704.     movmem(datap, dp, len );
  705.  
  706.     /* internet header */
  707.     inp->ver = 4;
  708.     inp->hdrlen = 5;
  709.     inp->tos = 0;
  710. /* inp->vht = 0x4500;*/   /* version 4, hdrlen 5, tos 0 */
  711.     inp->identification = intel16( ++ip_id );   /* was post inc */
  712. //    inp->frag = 0;
  713.     inp->ttl = 254;
  714.     inp->proto = UDP_PROTO;    /* udp */
  715. /* inp->ttlProtocol = (250<<8) + 6; */
  716.     inp->checksum = 0;
  717.     inp->source = intel( s->myaddr );
  718.     inp->destination = intel( s->hisaddr );
  719.     inp->checksum = ~checksum( inp, sizeof(in_Header));
  720.  
  721.  
  722.     /* compute udp checksum if desired */
  723.     if ( s->sock_mode & UDP_MODE_NOCHK )
  724.     udpp->checksum = 0;
  725.     else {
  726.     ph.src = inp->source;    /* already INTELled */
  727.     ph.dst = inp->destination;
  728.     ph.mbz = 0;
  729.     ph.protocol = UDP_PROTO;    /* udp */
  730.     ph.length = udpp->length;    /* already INTELled */
  731.  
  732.     ph.checksum = checksum(&pkt->udp, intel16(ph.length));
  733.     udpp->checksum =  ~checksum(&ph, sizeof(ph));
  734.     }
  735.  
  736.     if (_dbugxmit) (*_dbugxmit)(s,inp,udpp,0);
  737.     _eth_send( intel16( inp->length ));
  738.  
  739.     return ( len );
  740. }
  741.  
  742. /*
  743.  * udp_read - read data from buffer, does large buffering
  744.  */
  745. static int udp_read(udp_Socket *s, byte *datap, int maxlen)
  746. {
  747.     int x;
  748.  
  749.     if (maxlen < 0) maxlen = MAXINT;
  750.     if (( x = s->rdatalen ) > 0) {
  751.     if ( x > maxlen ) x = maxlen;
  752.     if ( x > 0 ) {
  753.             if (datap) movmem( s->rdata, datap, x );
  754.         if ( s->rdatalen -= x )
  755.                 movmem( s->rdata + x, s->rdata, s->rdatalen);
  756.     }
  757.     }
  758.     return( x );
  759. }
  760.  
  761. void _udp_cancel( in_Header *ip )
  762. {
  763.     int len;
  764.     udp_Header *up;
  765.     udp_Socket *s;
  766.  
  767.     /* match to a udp socket */
  768.     len = in_GetHdrlenBytes(ip);
  769.     up = (udp_Header *)((byte *)ip + len);    /* udp frame pointer */
  770.  
  771.     /* demux to active sockets */
  772.     for ( s = udp_allsocs; s; s = s->next )
  773.         if ( s->hisport != 0 &&
  774.              intel16( up->dstPort ) == s->hisport &&
  775.              intel16( up->srcPort ) == s->myport &&
  776.              intel( ip->destination ) == s->hisaddr ) break;
  777.     if ( !s ) {
  778.     /* demux to passive sockets */
  779.     for ( s = udp_allsocs; s; s = s->next )
  780.         if ( s->hisport == 0 && intel16( up->dstPort ) == s->myport ) break;
  781.     }
  782.     if (s) {
  783.         s->rdatalen = 0;
  784.     s->ip_type = 0;
  785.     }
  786. }
  787.  
  788. void *_tcp_lookup( longword hisip, word hisport, word myport )
  789. {
  790.     tcp_Socket *s;
  791.     for ( s = tcp_allsocs; s; s = s->next ) {
  792.         if ( ( myport == s->myport ) &&         /* always unique under WATTCP */
  793.              ( hisport == s->hisport ) &&
  794.              ( hisip == s->hisaddr ))
  795.                 return( s );
  796.     }
  797.     return( NULL );
  798. }
  799.  
  800.  
  801. void _tcp_cancel(in_Header *ip, int code, char *msg, longword dummyip )
  802. {
  803.     int len;
  804.     tcp_Socket *s;
  805.     tcp_Header *tp;
  806.  
  807.     len = in_GetHdrlenBytes(ip);    /* check work */
  808.  
  809.     tp = (tcp_Header *)((byte *)ip + len);    /* tcp frame pointer */
  810.  
  811.     /* demux to active sockets */
  812.     for ( s = tcp_allsocs; s; s = s->next ) {
  813.         if ( intel16( tp->srcPort) == s->myport &&
  814.              intel16( tp->dstPort ) == s->hisport &&
  815.              intel( ip->destination ) == s->hisaddr ) {
  816.                 switch (code) {
  817.                     /* halt it */
  818.                     case  1 : s->err_msg = (msg) ?
  819.                                 msg : "ICMP closed connection";
  820.                               s->rdatalen = s->datalen = 0;
  821.                               s->unhappy = false;
  822.                               tcp_abort( s );
  823.                 /*      if (s->dataHandler) s->dataHandler(s, 0, -1); */
  824.                               break;
  825.                     /* slow it down */
  826.                     case  2 : s->cwindow = 1;
  827.                               s->wwindow = 1;
  828.                               s->rto <<= 2;
  829.                               s->vj_sa <<= 2;
  830.                               s->vj_sd <<= 2;
  831.                               break;
  832.                     /* icmp redirect for host */
  833.                     case  5 : /* save his NEW network address */
  834.                               _arp_resolve(dummyip, &s->hisethaddr[0], 0);
  835.                               break;
  836.                 }
  837.  
  838.         }
  839.     }
  840. }
  841.  
  842. static int tcp_read(tcp_Socket *s, byte *datap, int maxlen)
  843. {
  844.     int x;
  845.  
  846.     if (maxlen < 0 ) maxlen = MAXINT;
  847.     if (( x = s->rdatalen) > 0) {
  848.     if ( x > maxlen ) x = maxlen;
  849.         if ( x > 0 ) {
  850.             if (datap) movmem( s->rdata, datap, x );
  851.             if (( s->rdatalen -= x ) > 0 ) {
  852.                 movmem( s->rdata + x, s->rdata, s->rdatalen );
  853.                 tcp_sendsoon( s );   /* update the window */
  854.             } else
  855.                 tcp_send( s, __LINE__ );      /* update window el-pronto */
  856.     }
  857.     } else if ( s->state == tcp_StateCLOSWT )
  858.         tcp_close( s );
  859.     return( x );
  860. }
  861.  
  862. /*
  863.  * Write data to a connection.
  864.  * Returns number of bytes written, == 0 when connection is not in
  865.  * established state.
  866.  */
  867. static tcp_write(tcp_Socket *s, byte *dp, int len)
  868. {
  869.     int x;
  870.  
  871.     if (len < 0 ) len = MAXINT;
  872.     /* no longer uses tcp_MaxData */
  873.     if ( s->state != tcp_StateESTAB ) len = 0;
  874.     if ( len > (x = s->maxrdatalen - s->datalen) ) len = x;
  875.     if ( len > 0 ) {
  876.         movmem( dp, s->data + s->datalen, len );
  877.  
  878.     s->datalen += len;
  879.     s->unhappy = true;    /* redundant because we have outstanding data */
  880.  
  881.         if ( s->sock_mode & TCP_LOCAL )
  882.             s->sock_mode &= ~TCP_LOCAL;
  883.         else {
  884.             if ( s->sock_mode & TCP_MODE_NONAGLE ) {
  885.                 tcp_send( s, __LINE__ );
  886.             } else {
  887.                 /* transmit if first data or reached MTU */
  888.                 /* not true MTU, but better than nothing */
  889.                 if (( s->datalen == len ) || ( s->datalen > (s->mss)/2 ))
  890.                     tcp_send( s, __LINE__ );
  891.                 else
  892.                     tcp_sendsoon( s );
  893.             }
  894.     }
  895.     }
  896.  
  897.     return ( len );
  898. }
  899.  
  900. /*
  901.  * Send pending data
  902.  */
  903. static void tcp_Flush(tcp_Socket *s)
  904. {
  905.     if ( s->datalen > 0 ) {
  906.         s->flags |= tcp_FlagPUSH;
  907.         tcp_send(s, __LINE__);
  908.     }
  909. }
  910.  
  911. /*
  912.  * Handler for incoming packets.
  913.  */
  914. static void udp_handler(in_Header *ip)
  915. {
  916.     udp_Header *up;
  917.     tcp_PseudoHeader ph;
  918.     word len;
  919.     byte *dp;
  920.     longword temp;
  921.     udp_Socket *s;
  922.  
  923.     temp = intel( ip->destination );
  924.  
  925.     if ( ((~temp & ~sin_mask) != 0) &&  /* not a broadcast packet*/
  926.         ((( temp - my_ip_addr) > multihomes )   /* not my address */
  927.         && my_ip_addr))                 /* and I know my address */
  928.           return;
  929.  
  930.  
  931.     len = in_GetHdrlenBytes(ip);
  932.     up = (udp_Header *)((byte *)ip + len);    /* udp segment pointer */
  933.     len = intel16( up->length );
  934.  
  935.     /* demux to active sockets */
  936.     for ( s = udp_allsocs; s; s = s->next ) {
  937.         if ( s->safetysig != SAFETYUDP ) {
  938. #ifndef RELEASE
  939.         if (debug_on) outs("chain error in udp\n");
  940. #endif /* RELEASE */
  941.         }
  942.         if ( s->hisport != 0 &&
  943.          intel16( up->dstPort ) == s->myport &&
  944.          intel16( up->srcPort ) == s->hisport &&
  945.              intel( ip->destination )   == s->myaddr     &&
  946.          intel( ip->source ) == s->hisaddr ) break;
  947.     }
  948.     if (_dbugrecv) (*_dbugrecv)(s,ip,up,0);
  949.     if ( !s ) {
  950.         /* demux to passive sockets */
  951.     for ( s = udp_allsocs; s; s = s->next )
  952.             if ( ((s->hisaddr == 0) || (s->hisaddr == 0xffffffff))
  953.               && intel16( up->dstPort ) == s->myport ) {
  954.                 s->hisaddr = intel( ip->source );
  955.                 s->hisport = intel16( up->srcPort );
  956.                 _arp_resolve(intel(ip->source), &s->hisethaddr[0], 0);
  957.                 // take on value of expected destination unless it
  958.                 // is broadcast
  959.                 if ( ip->destination != 0xffffffffL )
  960.                     s->myaddr = intel( ip->destination );
  961.         break;
  962.         }
  963.     }
  964.     if ( !s ) {
  965.     /* demux to broadcast sockets */
  966.     for ( s = udp_allsocs; s; s = s->next )
  967.             if ( (s->hisaddr == 0xffffffff) &&
  968.                  (intel16( up->dstPort ) == s->myport )) break;
  969.     }
  970.  
  971.     if ( !s ) {
  972. #ifndef RELEASE
  973.     if (debug_on) outs("discarding...\n");
  974. #endif /* RELEASE */
  975.     return;
  976.     }
  977.  
  978.     if ( up->checksum ) {
  979.     ph.src = ip->source;    /* already INTELled */
  980.     ph.dst = ip->destination;
  981.     ph.mbz = 0;
  982.     ph.protocol = UDP_PROTO;
  983.     ph.length = up->length;
  984.     ph.checksum =  checksum(up, len);
  985.     if (checksum(&ph, sizeof( tcp_PseudoHeader)) != 0xffff)
  986.         return;
  987.     }
  988.  
  989.     /* process user data */
  990.     if ( (len -= UDP_LENGTH ) > 0) {
  991.     dp = (byte *)( up );
  992.         if (s->dataHandler) s->dataHandler( s, &dp[ UDP_LENGTH ], len , &ph, up);
  993.     else {
  994.             if (len > s->maxrdatalen ) len = s->maxrdatalen;
  995.         movmem( &dp[ UDP_LENGTH ], s->rdata, len );
  996.         s->rdatalen = len;
  997.     }
  998.     }
  999. }
  1000.  
  1001. static void tcp_handler(in_Header *ip)
  1002. {
  1003.     tcp_Header *tp;
  1004.     tcp_PseudoHeader ph;
  1005.     int len;
  1006.     byte *dp;
  1007.     int diff;
  1008.     tcp_Socket *s;
  1009.     word flags;
  1010.     long diffticks, ldiff;    /* must be signed */
  1011.     long scheduleto;
  1012.  
  1013.  
  1014.     if ( (longword)(intel( ip->destination ) - my_ip_addr) > multihomes )
  1015.         return;
  1016.  
  1017.     len = in_GetHdrlenBytes(ip);
  1018.     len = intel16( ip->length ) - len;        /* len of tcp data */
  1019.  
  1020.     len = in_GetHdrlenBytes(ip);
  1021.     tp = (tcp_Header *)((byte *)ip + len);    /* tcp frame pointer */
  1022.     len = intel16( ip->length ) - len;        /* len of tcp data */
  1023.     flags = intel16( tp->flags );
  1024.  
  1025. #ifndef RELEASE
  1026.     if (debug_on > 1) {
  1027.         mono[160]++;
  1028.         colour[160]++;
  1029.         mono[162] = colour[162] = (flags & tcp_FlagSYN) ? 'S' : ' ';
  1030.         mono[164] = colour[164] = (flags & tcp_FlagACK) ? 'A' : ' ';
  1031.         mono[166] = colour[166] = (flags & tcp_FlagFIN) ? 'F' : ' ';
  1032.         mono[168] = colour[168] = (flags & tcp_FlagRST) ? 'R' : ' ';
  1033.     }
  1034. #endif /* RELEASE */
  1035.  
  1036.     /* demux to active sockets */
  1037.     for ( s = tcp_allsocs; s; s = s->next ) {
  1038.         if ( s->safetysig != SAFETYTCP ) {
  1039. #ifndef RELEASE
  1040.         if (debug_on) outs("chain error in tcp\n");
  1041. #endif /* RELEASE */
  1042.         }
  1043.     if ( s->hisport != 0 &&
  1044.          intel16( tp->dstPort ) == s->myport &&
  1045.          intel16( tp->srcPort ) == s->hisport &&
  1046.              intel( ip->destination )   == s->myaddr     &&
  1047.          intel( ip->source ) == s->hisaddr ) break;
  1048.     }
  1049.     if ( !s && (flags & tcp_FlagSYN)) {
  1050.     /* demux to passive sockets, must be a new session */
  1051.     for ( s = tcp_allsocs; s; s = s->next )
  1052.             if ((s->hisport == 0) && (intel16( tp->dstPort ) == s->myport )) {
  1053.                 s->myaddr = intel( ip->destination );
  1054.         break;
  1055.             }
  1056.     }
  1057.  
  1058.  
  1059.     if (_dbugrecv) (*_dbugrecv)(s,ip,tp,0);
  1060.     if ( !s ) {
  1061.         if (!(flags & tcp_FlagRST)) tcp_rst( ip, tp );
  1062.     return;
  1063.     }
  1064.  
  1065.     ph.src = ip->source;    /* already INTELled */
  1066.     ph.dst = ip->destination;
  1067.     ph.mbz = 0;
  1068.     ph.protocol = TCP_PROTO;
  1069.     ph.length = intel16( len );
  1070.     ph.checksum =  checksum(tp, len);
  1071.     if ( checksum(&ph, sizeof(ph)) != 0xffff ) {
  1072. #ifndef RELEASE
  1073.      if (debug_on) outs("bad tcp checksum \n");
  1074. #endif /* RELEASE */
  1075.  
  1076.          /* tester */
  1077.          ph.checksum =  checksum(tp, len);
  1078.          checksum(&ph, sizeof(ph));
  1079.  
  1080.          tcp_sendsoon( s );
  1081.      return;
  1082.     }
  1083.  
  1084. /* reset code */
  1085.     if ( flags & tcp_FlagRST ) {
  1086. #ifndef RELEASE
  1087.     if (debug_on) outs("\7\7\7\7\7\7\7connection reset\n");
  1088. #endif /* RELEASE */
  1089.         s->rdatalen = s->datalen = 0;
  1090.         s->err_msg = "Remote reset connection";
  1091.     s->state = tcp_StateCLOSED;
  1092. /*    if (s->dataHandler) s->dataHandler(s, 0, -1); */
  1093.     tcp_unthread(s);
  1094.     return;
  1095.     }
  1096.  
  1097.     if ( sock_inactive )
  1098.         s->inactive_to = set_timeout( sock_inactive );
  1099.  
  1100.  
  1101.     /* update our retransmission stuff */
  1102.     /* new algorithms */
  1103.     if (s->karn_count == 2) {
  1104.         s->karn_count = 0;
  1105. #ifdef DEBUG
  1106. #ifndef RELEASE
  1107.     if (debug_on > 1 ) printf("finally got it safely zapped from %u to ????\n",s->unacked);
  1108. #endif /* RELEASE */
  1109. #endif /* DEBUG */
  1110.     } else {
  1111.         if ( s->vj_last ) {
  1112.             /* unnecessary to use unhappy || s->datalen ) */
  1113.             if ((diffticks = set_ttimeout( 0 ) - s->vj_last) >= 0 ) {
  1114.                 /* we ignore the overnight case */
  1115.                 diffticks -= (longword)( s->vj_sa >> 3 );
  1116.                 s->vj_sa += (int)diffticks;
  1117.                 if (diffticks < 0)
  1118.                     diffticks = - diffticks;
  1119.                 diffticks -= (s->vj_sd >> 2);
  1120.                 s->vj_sd += (int)diffticks;
  1121.                 if (s->vj_sa > MAXVJSA) s->vj_sa = MAXVJSA;
  1122.                 if (s->vj_sd > MAXVJSD) s->vj_sd = MAXVJSD;
  1123.             }
  1124.             /* only recompute rtt hence rto after success */
  1125.             s->rto = 1 + ((s->vj_sa >> 2) + (s->vj_sd)) >> 1 ;
  1126. #ifdef DEBUG
  1127. #ifndef RELEASE
  1128.         if (debug_on > 1 ) printf("rto  %u  sa  %u  sd  %u   cwindow %u  wwindow %u  unacked %u\n",
  1129.         s->rto, s->vj_sa, s->vj_sd, s->cwindow, s->wwindow, s->unacked );
  1130. #endif /* RELEASE */
  1131. #endif /* DEBUG */
  1132.     }
  1133.         s->karn_count = 0;
  1134.         if ( s->wwindow++ >= s->cwindow ) {
  1135.             s->cwindow++;
  1136.             s->wwindow = 0;
  1137.         }
  1138.     }
  1139.     /* all new */
  1140.     scheduleto = set_ttimeout( s->rto + 2 );
  1141.     if ( s->rtt_time < scheduleto ) s->rtt_time = scheduleto;
  1142.  
  1143.  
  1144.     switch ( s->state ) {
  1145.  
  1146.     case tcp_StateLISTEN:    /* accepting SYNs */
  1147.             /* save his ethernet address */
  1148.             if ( _pktipofs )
  1149.                 movmem(&((((eth_Header *)ip) - 1)->source[0]), &s->hisethaddr[0], sizeof(eth_address));
  1150.             if ( flags & tcp_FlagSYN ) {
  1151.  
  1152.                 if ( ip->tos > s->tos )
  1153.                     s->tos = ip->tos;
  1154.                 else if ( ip->tos < s->tos ) {
  1155.                     /* RFC 793 says we should close connection */
  1156.                     /* we best not do that while SunOS ignores TOS */
  1157.                 }
  1158.  
  1159.                 s->acknum = intel( tp->seqnum ) + 1;
  1160.         s->hisport = intel16( tp->srcPort );
  1161.         s->hisaddr = intel( ip->source );
  1162.         s->flags = tcp_FlagSYN | tcp_FlagACK;
  1163.                 s->state = tcp_StateSYNREC;
  1164.         s->unhappy = true;
  1165.                 tcp_send(s, __LINE__);    /* we must respond immediately */
  1166.  
  1167.         s->timeout = set_timeout( tcp_TIMEOUT );
  1168.         } else
  1169.         tcp_rst( ip , tp );  /* send a reset */
  1170.  
  1171.             return;
  1172.  
  1173.     case tcp_StateSYNSENT:  /* added ACK Section */
  1174.         if ( flags & tcp_FlagSYN ) {
  1175.  
  1176.                 if ( ip->tos > s->tos )
  1177.                     s->tos = ip->tos;
  1178.                 else if ( ip->tos < s->tos ) {
  1179.                     /* RFC 793 says we should close connection */
  1180.                     /* we best not do that while SunOS ignores TOS */
  1181.                 }
  1182.  
  1183.                 s->flags = tcp_FlagACK;
  1184.         s->timeout = set_timeout( tcp_TIMEOUT );
  1185.  
  1186.         /* FlagACK means connection established, else SYNREC */
  1187.         if ( flags & tcp_FlagACK) {
  1188.             /* but is it for the correct session ? */
  1189.                 if (tp->acknum == intel(s->seqnum + 1)) {
  1190.                 s->state = tcp_StateESTAB;
  1191.                 s->seqnum++;    /* good increment */
  1192.                 s->acknum = intel( tp->seqnum  ) + 1;   /* 32 bits */
  1193.                 tcp_ProcessData(s, tp, len);    /* someone may try it */
  1194.                 s->unhappy = true;             /* rely on their attempts */
  1195.                 tcp_send( s, __LINE__ );
  1196.             } else {
  1197.                 /* wrong ack, force a RST and resend SYN soon*/
  1198.                 s->flags = tcp_FlagRST;
  1199.                 s->unhappy = true;
  1200.                 tcp_send( s, __LINE__ );
  1201.                 s->flags = tcp_FlagSYN;
  1202.                 tcp_send( s, __LINE__ );
  1203.             }
  1204.         } else {
  1205.             s->acknum++;
  1206.             s->state = tcp_StateSYNREC;
  1207.                     return;
  1208.         }
  1209.             } else
  1210.                 tcp_rst( ip, tp );
  1211.         break;
  1212.  
  1213.     case tcp_StateSYNREC:    /* recSYNSENT, sentACK, waiting  EST */
  1214.         if ( flags & tcp_FlagSYN ) {
  1215.         s->flags = tcp_FlagSYN | tcp_FlagACK;
  1216.         s->unhappy = true;
  1217.                 tcp_send(s, __LINE__);
  1218.         s->timeout = set_timeout( tcp_TIMEOUT );
  1219.                 return;
  1220.         }
  1221.         if ( (flags & tcp_FlagACK) && (intel( tp->acknum ) == (s->seqnum + 1))) {
  1222.                 if ( (s->window = intel16( tp->window )) > 0x7fff )
  1223.                     s->window = 0x7fff;
  1224.         s->flags = tcp_FlagACK;
  1225.                 s->state = tcp_StateESTAB;
  1226.                 s->seqnum++;
  1227.                 s->timeout = 0;     /* never timeout */
  1228.                 s->unhappy = false;
  1229.                 return;
  1230.         }
  1231.  
  1232.         break;
  1233.     case tcp_StateESTAB:
  1234.         case tcp_StateESTCL:
  1235.         case tcp_StateCLOSWT:
  1236.  
  1237.             /* handle lost SYN */
  1238.             if ((flags & tcp_FlagSYN) && (flags & tcp_FlagACK)) {
  1239.                 tcp_send( s, __LINE__ );
  1240.                 return;
  1241.             }
  1242.  
  1243.         if ( !(flags & tcp_FlagACK)) return;  /* must ack somthing */
  1244.             if ( flags & tcp_FlagSYN ) {
  1245.                 tcp_rst( ip , tp );
  1246.                 return;
  1247.             }
  1248.         s->timeout = 0l;    /* we do not timeout at this point */
  1249.  
  1250.         /* process ack value in packet - but only if it falls
  1251.          * within current window */
  1252.  
  1253.         ldiff = intel( tp->acknum ) - s->seqnum;
  1254.         diff = (int) ldiff;
  1255.  
  1256.             if ( ldiff >= 0 && diff <= s->datalen ) {
  1257.         s->datalen -= diff;
  1258.                 s->unacked -= diff;
  1259.                 if (s->datalen < 0) s->datalen = 0; /* remote proto error */
  1260.                 if ( s->queuelen ) {
  1261.                     s->queue += diff;
  1262.                     s->queuelen -= diff;
  1263.                 } else
  1264.                     movmem(s->data + diff, s->data, s->datalen );
  1265.         s->seqnum += ldiff;
  1266.             } else {
  1267. #ifdef DEBUG
  1268. #ifndef RELEASE
  1269.     if(debug_on >1) printf("tcphandler confused so set unacked back to 0 from %u\n",s->unacked);
  1270. #endif /* RELEASE */
  1271. #endif DEBUG
  1272.                 s->unacked = 0;
  1273.             }
  1274.             if (s->unacked < 0) s->unacked = 0;
  1275.  
  1276.         s->flags = tcp_FlagACK;
  1277.         tcp_ProcessData(s, tp, len);
  1278.  
  1279.             if (( flags & tcp_FlagFIN ) && (s->state != tcp_StateCLOSWT )
  1280.                 && ( s->acknum == intel( tp->seqnum ))) {
  1281.                 s->acknum ++;
  1282.                 if ( ! s->err_msg ) s->err_msg = "Connection closed";
  1283.                 s->state = tcp_StateCLOSWT;
  1284.                 tcp_send( s, __LINE__ );
  1285.                 s->state = tcp_StateLASTACK;
  1286.                 s->flags |= tcp_FlagFIN;
  1287.                 s->unhappy = true;
  1288.             }
  1289.  
  1290.             if ( diff > 0 || len > 0 ) {
  1291.                 /* need to update window, but how urgent ??? */
  1292.                 if ( diff > 0 || (len > (s->mss >> 1))) {
  1293.                     tcp_send( s, __LINE__ );
  1294.                 } else
  1295.                     tcp_sendsoon( s );
  1296.  
  1297.             }
  1298.             if ( s->state == tcp_StateESTCL )
  1299.                 tcp_close( s );
  1300.             return;
  1301.  
  1302.     case tcp_StateFINWT1:
  1303.         /* They have not necessarily read all the data yet, we must
  1304.            still supply it as requested */
  1305.  
  1306.         ldiff = intel( tp->acknum ) - s->seqnum;
  1307.         diff = (int) ldiff;
  1308.         if ( ldiff >= 0 && diff <= s->datalen ) {
  1309.         s->datalen -= diff;
  1310.                 s->unacked -= diff;
  1311.                 if (s->datalen < 0) s->datalen = 0;
  1312.                 if ( s->queuelen ) {
  1313.                     s->queue += diff;
  1314.                     s->queuelen -= diff;
  1315.                 } else
  1316.                     movmem(s->data + diff, s->data, s->datalen );
  1317.         s->seqnum += ldiff;
  1318.                 if (ldiff == 0 || s->unacked < 0) s->unacked = 0;
  1319.  
  1320.         }
  1321.  
  1322.         /* they may still be transmitting data, we must read it */
  1323.  
  1324.         tcp_ProcessData(s, tp, len);
  1325.  
  1326.         /* check if other tcp has acked all sent data and is ready
  1327.            to change states */
  1328.  
  1329.             if ( (flags & (tcp_FlagFIN|tcp_FlagACK) ) == (tcp_FlagFIN|tcp_FlagACK)) {
  1330.         /* trying to do similtaneous close */
  1331.         if (( intel( tp->acknum ) >= s->seqnum + 1 ) &&
  1332.             ( intel( tp->seqnum) == s->acknum )) {
  1333.             s->seqnum++;
  1334. // we shouldn't be inc'ing the ack
  1335. //                  s->acknum++;
  1336.                     s->flags = tcp_FlagACK;
  1337.                     tcp_send( s, __LINE__ );
  1338.                     s->unhappy = false;
  1339.                     s->timeout = set_timeout( 2 );
  1340.                     s->state = tcp_StateCLOSED;
  1341.         }
  1342.         } else if ( flags & tcp_FlagACK ) {
  1343.         /* other side is legitimately acking our fin */
  1344.         if (( intel( tp->acknum ) == s->seqnum + 1 ) &&
  1345.             ( intel( tp->seqnum ) == s->acknum ) &&
  1346.             (  s->datalen == 0 )) {
  1347.                         s->seqnum++;
  1348.                         s->acknum++;
  1349.                         s->state = tcp_StateFINWT2;
  1350.                         s->timeout = set_timeout( 3 );
  1351.                         s->unhappy = false; /* we don't send anything */
  1352.         }
  1353.         }
  1354.         break;
  1355.  
  1356.     case tcp_StateFINWT2:
  1357.  
  1358.         /* they may still be transmitting data, we must read it */
  1359.         tcp_ProcessData(s, tp, len);
  1360.  
  1361.             if ((flags & (tcp_FlagACK | tcp_FlagFIN)) ==
  1362.                   (tcp_FlagACK | tcp_FlagFIN)) {
  1363.         if (( intel( tp->acknum ) == s->seqnum ) &&
  1364.             ( intel( tp->seqnum ) == s->acknum )) {
  1365.             s->acknum++;
  1366.             s->flags = tcp_FlagACK;
  1367.                     tcp_send( s, __LINE__ );
  1368.             s->unhappy = false;    /* we don't send anything */
  1369.             s->timeout = set_timeout( 2 );
  1370.                     s->state = tcp_StateCLOSED;
  1371.                     return;
  1372.         }
  1373.         }
  1374.         break;
  1375.  
  1376.     case tcp_StateCLOSING:
  1377.         if ((flags & (tcp_FlagACK | tcp_FlagFIN)) == tcp_FlagACK ) {
  1378.         if (( tp->acknum == intel(s->seqnum) ) &&
  1379.             ( tp->seqnum == intel(s->acknum))) {
  1380.             s->state = tcp_StateTIMEWT;
  1381.             s->timeout = set_timeout( tcp_TIMEOUT );
  1382.             s->unhappy = false;
  1383.         }
  1384.         }
  1385.         break;
  1386.  
  1387.     case tcp_StateLASTACK:
  1388.         if ( flags & tcp_FlagFIN ) {
  1389.         /* they lost our two packets, back up */
  1390.         s->flags = tcp_FlagACK | tcp_FlagFIN;
  1391.                 tcp_send( s, __LINE__ );
  1392.                 s->unhappy = TRUE;  /* FALSE; */
  1393.                 return;
  1394.         } else {
  1395.         if (( intel( tp->acknum ) == (s->seqnum + 1 )) &&
  1396.             ( intel( tp->seqnum ) == s->acknum )) {
  1397.             s->state = tcp_StateCLOSED;     /* no 2msl necessary */
  1398.             s->unhappy = false;             /* we're done */
  1399.                         return;
  1400.             }
  1401.         }
  1402.         break;
  1403.  
  1404.     case tcp_StateTIMEWT:
  1405.             if ( flags & (tcp_FlagACK | tcp_FlagFIN) == (tcp_FlagACK | tcp_FlagFIN)) {
  1406.                 /* he needs an ack */
  1407.                 s->flags = tcp_FlagACK;
  1408.                 tcp_send( s, __LINE__ );
  1409.                 s->unhappy = false;
  1410.                 s->state = tcp_StateCLOSED;     /* support 2 msl in rst code */
  1411.             }
  1412.             break;
  1413.     }
  1414.     if (s->unhappy) tcp_sendsoon(s);
  1415. }
  1416.  
  1417. /*
  1418.  * Process the data in an incoming packet.
  1419.  * Called from all states where incoming data can be received: established,
  1420.  * fin-wait-1, fin-wait-2
  1421.  */
  1422. static tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len)
  1423. {
  1424.     long ldiff;
  1425.     int diff, x;
  1426.     word flags;
  1427.     byte *dp;
  1428.  
  1429.     word *options, numoptions, opt_temp;
  1430.  
  1431.     if ( (s->window = intel16( tp->window )) > 0x7fff )
  1432.         s->window = 0x7fff;
  1433.  
  1434.     flags = intel16( tp->flags );
  1435.     ldiff = s->acknum - intel( tp->seqnum );
  1436.  
  1437.     if ( flags & tcp_FlagSYN ) ldiff--;  /* back up to 0 */
  1438.     diff = (int) ldiff;
  1439.  
  1440.     /* find the data portion */
  1441.     x = tcp_GetDataOffset(tp) << 2;    /* quadword to byte format */
  1442.     dp = (byte *)tp + x;
  1443.  
  1444.     /* process those options */
  1445.     if ( (numoptions = x - sizeof( tcp_Header )) != 0 ) {
  1446.     options = (word *)((byte *)(tp) + sizeof( tcp_Header));
  1447.     while ( numoptions-- > 0 ) {
  1448.         switch ( *options++ ) {
  1449.         case  0 : numoptions = 0;    /* end of options */
  1450.               break;
  1451.         case  1 : break;        /* nop */
  1452.  
  1453.               /* we are very liberal on MSS stuff */
  1454.         case  2 : if (*options == 2) {
  1455.                   opt_temp = intel16( *(word*)(&options[1]));
  1456.                   if (opt_temp < s->mss )
  1457.                   s->mss = opt_temp;
  1458.               }
  1459.               numoptions -= 2 + *options;
  1460.               options += *options;
  1461.               break;
  1462.         }
  1463.     }
  1464.     }
  1465.     /* done option processing */
  1466.  
  1467.     len -= x;        /* remove the header length */
  1468.     if ( ldiff >= 0 ) {  /* skip already received bytes */
  1469.     dp += diff;
  1470.     len -= diff;
  1471.  
  1472.     if (s->dataHandler) {
  1473.         s->acknum += s->dataHandler(s, dp, len);
  1474.     } else {
  1475.         /* no handler, just dump to buffer, should be indexed, handles goofs */
  1476.         /* limit receive size to our window */
  1477.         if ( s->rdatalen >= 0 ) {
  1478.                 if ( len > ( x = s->maxrdatalen - s->rdatalen )) {
  1479.             len = x;
  1480.                 }
  1481.         if ( len > 0 ) {
  1482.             s->acknum += len;    /* our new ack begins at end of data */
  1483.                     movmem(dp, s->rdata + s->rdatalen, len );
  1484.             s->rdatalen += len;
  1485. /*
  1486.                     s->karn_count = 3;
  1487. */
  1488.         }
  1489.         }
  1490.         }
  1491.         s->unhappy = (s->datalen) ? true : false;
  1492.         if (ldiff == 0 && s->unacked && chk_timeout( s->rtt_lasttran )) {
  1493. #ifdef DEBUG
  1494. #ifndef RELEASE
  1495.         if(debug_on >1) printf("data process timeout so set unacked back to 0 from %u\n",s->unacked);
  1496. #endif /* RELEASE */
  1497. #endif DEBUG
  1498.             s->unacked = 0;
  1499.         }
  1500.     } else {
  1501.         tcp_sendsoon( s );
  1502.     }
  1503.  
  1504.     s->timeout = set_timeout( tcp_TIMEOUT );
  1505.     return;
  1506. }
  1507.  
  1508. /*
  1509.  * Format and send an outgoing segment
  1510.  */
  1511.  
  1512. static tcp_send(tcp_Socket *s, int line)
  1513. {
  1514.     tcp_PseudoHeader ph;
  1515.     struct _pkt {
  1516.     in_Header in;
  1517.     tcp_Header tcp;
  1518.     word maxsegopt[2];
  1519.     } *pkt;
  1520.     byte *dp;
  1521.     in_Header *inp;
  1522.     tcp_Header *tcpp;
  1523.     int senddatalen, sendtotlen, sendpktlen, startdata, sendtotdata;
  1524.  
  1525.     int ippkt;         /* 1..s->cwindow */
  1526.  
  1527.     s->recent = 0;
  1528.     pkt = (struct _pkt *)_eth_formatpacket(&s->hisethaddr[0], /*0x800*/ 8);
  1529.     dp = (byte *) &pkt->maxsegopt;  /* dp constant for multi-packet sends */
  1530.     inp = &pkt->in;
  1531.     tcpp = &pkt->tcp;
  1532.  
  1533.  
  1534.     /* this is our total possible send size */
  1535.     if ( s->karn_count != 2 ) {
  1536.         /* BUG FIX : jason dent found this */
  1537. /*      sendtotdata = min( s->datalen - s->unacked, s->window );  */
  1538.         sendtotdata = max (min ( s->datalen, s->window ) - s->unacked, 0);
  1539.         startdata = s->unacked;
  1540.     } else {
  1541.         sendtotdata = (s->datalen >= s->window)? s->window : s->datalen;
  1542.         startdata = 0;
  1543.     }
  1544. /*
  1545.     if (sendtotdata < 0) sendtotdata = 0;
  1546. */
  1547.     sendtotlen = 0;    /* running count of what we've sent */
  1548.  
  1549.     /* step through our packets */
  1550.     for ( ippkt = 1; ippkt <= s->cwindow; ++ippkt ) {
  1551.         /* adjust size for each packet */
  1552.         senddatalen = min( sendtotdata, s->mss );
  1553.  
  1554.     /*
  1555.         sendpktlen = senddatalen + sizeof( tcp_Header ) + sizeof( in_Header );
  1556.         inp->length = intel16( sendpktlen );
  1557.     */
  1558.         /* tcp header */
  1559.         tcpp->srcPort = intel16( s->myport );
  1560.         tcpp->dstPort = intel16( s->hisport );
  1561.         tcpp->seqnum = intel( s->seqnum + startdata ); /* unacked - no longer sendtotlen */
  1562.         tcpp->acknum = intel( s->acknum );
  1563.  
  1564.         tcpp->window = intel16( s->maxrdatalen - s->rdatalen );
  1565.         tcpp->flags = intel16( s->flags | 0x5000 );
  1566.         tcpp->checksum = 0;
  1567.         tcpp->urgentPointer = 0;
  1568.  
  1569.         /* do options if this is our first packet */
  1570.         if ( s->flags & tcp_FlagSYN ) {
  1571.             sendpktlen = sizeof( tcp_Header ) + sizeof( in_Header ) + 4;
  1572.             tcpp->flags = intel16( intel16( tcpp->flags) + 0x1000 );
  1573.             pkt->maxsegopt[0] = 0x0402;
  1574.             pkt->maxsegopt[1] = intel16( s->mss );
  1575.             dp += 4;
  1576.         } else {
  1577.             /* handle packets with data */
  1578.             if (senddatalen > 0) {
  1579.                 sendpktlen = senddatalen + sizeof( tcp_Header ) + sizeof( in_Header );
  1580.  
  1581.                 /* get data from appropriate place */
  1582.                 if (s->queuelen) movmem(s->queue + startdata, dp, senddatalen );
  1583.                 else movmem(s->data + startdata, dp, senddatalen);
  1584. /*                dp[ senddatalen ] = 0; */
  1585.             } else {
  1586.             /* handle no-data, not-first-SYN packets */
  1587.                 sendpktlen = sizeof( tcp_Header ) + sizeof( in_Header );
  1588.             }
  1589.         }
  1590.  
  1591.         /* internet header */
  1592.         memset( inp, 0, sizeof( in_Header ));
  1593.         inp->ver = 4;
  1594.         inp->hdrlen = 5;
  1595.         inp->tos = s->tos;
  1596.         inp->identification = intel16( ++ip_id );   /* was post inc */
  1597. //        inp->frag = 0;
  1598.         inp->ttl = 254;
  1599.         inp->proto = TCP_PROTO;
  1600.         inp->checksum = 0;
  1601.         inp->source = intel( s->myaddr );
  1602.         inp->destination = intel( s->hisaddr );
  1603.         inp->length = intel16( sendpktlen );
  1604.  
  1605.         inp->checksum = ~checksum( inp, sizeof(in_Header));
  1606.  
  1607.         /* compute tcp checksum */
  1608.         ph.src = inp->source;   /* already INTELled */
  1609.         ph.dst = inp->destination;
  1610.         ph.mbz = 0;
  1611.         ph.protocol = 6;
  1612.         ph.length = intel16( sendpktlen - sizeof(in_Header));
  1613. /*
  1614.         ph.checksum = checksum(&pkt->tcp, (sendpktlen - sizeof(in_Header) +1) & 0xfffe);
  1615. */
  1616.         ph.checksum = checksum(&pkt->tcp, sendpktlen - sizeof(in_Header));
  1617.  
  1618.         tcpp->checksum = ~checksum(&ph, sizeof(ph));
  1619.  
  1620.         if (_dbugxmit) (*_dbugxmit)(s,inp,tcpp, line);
  1621. #ifndef RELEASE
  1622.     if (debug_on > 1) {
  1623.         mono[0]++;
  1624.         colour[0]++;
  1625.         mono[2] = colour[2] = (s->flags & tcp_FlagSYN) ? 'S' : ' ';
  1626.         mono[4] = colour[4] = (s->flags & tcp_FlagACK) ? 'A' : ' ';
  1627.         mono[6] = colour[6] = (s->flags & tcp_FlagFIN) ? 'F' : ' ';
  1628.         mono[8] = colour[8] = (s->flags & tcp_FlagRST) ? 'R' : ' ';
  1629.     }
  1630. #endif /* RELEASE */
  1631.     if ( _eth_send( intel16( inp->length ))) { /* encounterred error */
  1632.             tcp_sendsoon( s );
  1633.             return;
  1634.         }
  1635.  
  1636.         /* do next ip pkt */
  1637.         sendtotlen += senddatalen;
  1638.         startdata += senddatalen;
  1639.         sendtotdata -= senddatalen;
  1640.         if (sendtotdata <= 0 ) break;
  1641.     }
  1642.     s->unacked = startdata;
  1643. #ifdef DEBUG
  1644. #ifndef RELEASE
  1645. if (debug_on) printf(" Sent %u/%u bytes in %u/%u packets  with (%u) unacked  SYN %lu  line %u\n",
  1646.     sendtotlen, s->window, ippkt, s->cwindow, s->unacked, s->seqnum, line);
  1647. #endif /* RELEASE */
  1648. #endif DEBUG
  1649.     s->vj_last = 0;
  1650.     if ( s->karn_count == 2 ) {
  1651.         if (s->rto) s->rto = (s->rto * 3) / 2;
  1652.         else s->rto = 4;
  1653.     } else {
  1654.         /* vj_last nonzero if we expect an immediate response */
  1655.         if (s->unhappy || s->datalen)
  1656.             s->vj_last = set_ttimeout( 0 );
  1657.     s->karn_count = 0;
  1658.     }
  1659.     s->rtt_time = set_ttimeout( s->rto + 2 );
  1660.     if (sendtotlen > 0 ) s->rtt_lasttran =  s->rtt_time + s->rto;
  1661. }
  1662. /*
  1663.  * Format and send a reset tcp packet
  1664.  */
  1665. tcp_rst( in_Header *his_ip, tcp_Header *oldtcpp)
  1666. {
  1667.     tcp_PseudoHeader ph;
  1668.     struct _pkt {
  1669.         in_Header in;
  1670.         tcp_Header tcp;
  1671.     word maxsegopt[2];
  1672.     } *pkt, *his_pkt;
  1673.  
  1674.     static longword nextrst = 0L;
  1675.     word oldflags;
  1676.     in_Header *inp;
  1677.     tcp_Header *tcpp;
  1678.     eth_Header *eth;
  1679.     int sendtotlen;    /* length of packet */
  1680.     int temp;
  1681.     longword templong;
  1682.  
  1683.     /* see RFC 793 page 65 for details */
  1684.  
  1685.     if ( !chk_timeout( nextrst )) return;
  1686.     nextrst = set_ttimeout( 1 );
  1687.  
  1688.     oldflags = intel16( oldtcpp->flags );
  1689.     if (oldflags & tcp_FlagRST ) return;
  1690. #ifdef NEVER
  1691.     if ( (oldflags & (tcp_FlagACK | tcp_FlagFIN)) == (tcp_FlagACK | tcp_FlagFIN) ){
  1692.         templong = oldtcpp->seqnum;
  1693.         oldtcpp->seqnum = oldtcpp->acknum;
  1694.         oldtcpp->acknum = templong;
  1695.         oldflags = tcp_FlagACK;
  1696.     } else if ((oldflags & (tcp_FlagSYN | tcp_FlagACK)) ==  tcp_FlagSYN ) {
  1697.         oldtcpp->acknum = intel( intel( oldtcpp->seqnum ) + 1 );
  1698.         oldtcpp->seqnum = 0;
  1699.         oldflags = tcp_FlagACK | tcp_FlagRST;
  1700.     } else if ( oldflags & tcp_FlagACK ) {
  1701.         oldtcpp->seqnum = oldtcpp->acknum;
  1702.         oldtcpp->acknum = 0;
  1703.     } else {
  1704.         oldtcpp->acknum = intel( intel(oldtcpp->seqnum) + 1);
  1705.         oldtcpp->seqnum = 0;
  1706.     }
  1707.     if ( oldflags & ( tcp_FlagFIN | tcp_FlagSYN ) == 0 )
  1708.         oldflags ^= tcp_FlagACK | tcp_FlagRST;
  1709.  
  1710.     if ( oldflags & tcp_FlagACK ) {
  1711.         oldtcpp->seqnum = oldtcpp->acknum;
  1712.  
  1713. #else
  1714.     /* better strategy - Dean Roth */
  1715.     if ( oldflags & tcp_FlagACK ) {
  1716.         oldtcpp->seqnum = oldtcpp->acknum;
  1717.         oldtcpp->acknum = 0;
  1718.     } else {
  1719.         temp = intel16( his_ip->length) - in_GetHdrlenBytes( his_ip );
  1720.         oldtcpp->acknum = intel( intel( oldtcpp->seqnum ) + temp );
  1721.         oldtcpp->seqnum = 0;
  1722.     }
  1723.     oldflags = tcp_FlagRST;
  1724. #endif
  1725.  
  1726.     his_pkt  = (struct _pkt*)( his_ip );
  1727.  
  1728.     /* convoluted mechanism - reads his ethernet address or garbage */
  1729.     eth = _eth_hardware( his_ip );
  1730.  
  1731.     pkt = (struct _pkt *)_eth_formatpacket( eth, 8);
  1732.     inp = &pkt->in;
  1733.     tcpp = &pkt->tcp;
  1734.  
  1735.     sendtotlen = sizeof( tcp_Header ) + sizeof( in_Header );
  1736.     memset( inp, 0, sizeof( in_Header ));
  1737.     inp->length = intel16( sendtotlen );
  1738.  
  1739.     /* tcp header */
  1740.     tcpp->srcPort = oldtcpp->dstPort;
  1741.     tcpp->dstPort = oldtcpp->srcPort;
  1742.     tcpp->seqnum = oldtcpp->seqnum;
  1743.     tcpp->acknum = oldtcpp->acknum;
  1744.     tcpp->window = 0;
  1745. /*    tcpp->flags = intel16( oldflags ); */
  1746.     /* BUG FIX : jason dent found this thanks to SCO */
  1747.     tcpp->flags = intel16( (oldflags & 0x0fff ) | 0x5000 );
  1748.     tcpp->checksum = 0;
  1749.     tcpp->urgentPointer = 0;
  1750.  
  1751.     /* internet header */
  1752.     inp->ver = 4;
  1753.     inp->hdrlen = 5;
  1754.     inp->tos = his_ip->tos;
  1755.     inp->identification = intel16( ++ip_id );
  1756. //    inp->frag = 0;
  1757.     inp->ttl = 254;
  1758.     inp->proto = TCP_PROTO;
  1759.     inp->checksum = 0;
  1760.     inp->source = his_ip->destination;
  1761.     inp->destination = his_ip->source;
  1762.  
  1763.     inp->checksum = ~checksum( inp, sizeof(in_Header))/* 0*/;
  1764.  
  1765.     /* compute tcp checksum */
  1766.     ph.src = inp->source;    /* already INTELled */
  1767.     ph.dst = inp->destination;
  1768.     ph.mbz = 0;
  1769.     ph.protocol = 6;
  1770.     ph.length = intel16( sendtotlen - sizeof(in_Header));
  1771.  
  1772.     ph.checksum = checksum(&pkt->tcp, sizeof(tcp_Header));
  1773.     tcpp->checksum =  ~checksum(&ph, sizeof(ph));
  1774.  
  1775.     if (_dbugxmit) (*_dbugxmit)(NULL,inp,tcpp,__LINE__);
  1776.     _eth_send( intel16( inp->length ));
  1777. }
  1778.  
  1779.  
  1780.  
  1781.  
  1782. /**********************************************************************
  1783.  * socket functions
  1784.  **********************************************************************/
  1785.  
  1786. /* socket based stuff */
  1787.  
  1788. /*
  1789.  * sock_read - read a socket with maximum n bytes
  1790.  *         - busywaits until buffer is full but calls s->usr_yield
  1791.  *         - returns count also when connection gets closed
  1792.  */
  1793. sock_read(sock_type *s, byte *dp, int len )
  1794. {
  1795.     int templen, count;
  1796.     count = 0;
  1797.     do {
  1798.     if ( s->udp.ip_type == UDP_PROTO )
  1799.             templen = udp_read( &(s->udp), dp, len );
  1800.     else
  1801.             templen = tcp_read( &(s->tcp), dp, len);
  1802.         if (s->tcp.usr_yield) (s->tcp.usr_yield)();
  1803.         if (templen < 1 ) {
  1804.             if (!tcp_tick( s )) return( count );
  1805.         } else {
  1806.             count += templen;
  1807.             dp += templen;
  1808.             len -= templen;
  1809.         }
  1810.     } while ( len );
  1811.     return( count );
  1812. }
  1813. /*
  1814.  * sock_fead - read a socket with maximum n bytes
  1815.  *         - does not busywait until buffer is full
  1816.  */
  1817. sock_fastread(sock_type *s, byte *dp, int len )
  1818. {
  1819.     if ( s->udp.ip_type == UDP_PROTO )
  1820.         len = udp_read( &(s->udp), dp, len );
  1821.     else
  1822.         len = tcp_read( &(s->tcp), dp, len);
  1823.     return( len );
  1824. }
  1825.  
  1826.  
  1827. /*
  1828.  * sock_write - writes data and returns length written
  1829.  *          - does not perform flush
  1830.  *          - repeatedly calls s->usr_yield
  1831.  */
  1832.  
  1833. sock_write(sock_type *s, byte *dp, int len)
  1834. {
  1835.     int offset, oldlen, oldmode, proto;
  1836.  
  1837.     oldlen = len;
  1838.     offset = 0;
  1839.  
  1840.     proto = (s->udp.ip_type == TCP_PROTO);
  1841.     if ( proto ) oldmode = s->tcp.flags & tcp_FlagPUSH;
  1842.     while ( len  > 0) {
  1843.         if (proto) {
  1844.             s->tcp.flags |= oldmode;
  1845.             offset += tcp_write( &(s->udp), &dp[ offset ], len);
  1846.         } else
  1847.             offset += udp_write( &(s->tcp), &dp[ offset ], len );
  1848.     len = oldlen - offset;
  1849.     if (s->udp.usr_yield)(s->udp.usr_yield)();
  1850.     if (!tcp_tick(s)) return( 0 );
  1851.     }
  1852.     return( oldlen );
  1853. }
  1854.  
  1855.  
  1856.  
  1857. sock_fastwrite(sock_type *s, byte *dp, int len)
  1858. {
  1859.     return( ( s->udp.ip_type == UDP_PROTO ) ?
  1860.         udp_write( s, dp, len ) :
  1861.         tcp_write( s, dp, len) );
  1862. }
  1863.  
  1864. int sock_setbuf( sock_type *s, byte *dp, int len )
  1865. {
  1866.     if ( len < 0 ) return( 0 );
  1867.     if (len == 0 || dp == NULL ) {
  1868.         s->tcp.rdata = s->tcp.rddata;
  1869.         s->tcp.maxrdatalen = tcp_MaxBufSize;
  1870.     } else {
  1871.         s->tcp.rdata = dp;
  1872.         s->tcp.maxrdatalen = len;
  1873.     }
  1874.     return( s->tcp.maxrdatalen);
  1875. }
  1876.  
  1877. int sock_enqueue(sock_type *s, byte *dp, int len )
  1878. {
  1879.     int written;
  1880.  
  1881.     if ( len < 0 ) return( 0 );
  1882.     if ( s->udp.ip_type == UDP_PROTO ) {
  1883.         do {
  1884.             written = udp_write( s, dp, len );
  1885.             dp += written;
  1886.         } while (len -= written > 0);
  1887.     } else {
  1888.         s->tcp.queue = dp;
  1889.         s->tcp.queuelen = len;
  1890.         s->tcp.datalen = len;
  1891.         tcp_send( s, __LINE__ );  /* start sending it */
  1892.     }
  1893.     return( len );
  1894. }
  1895.  
  1896. void sock_noflush( sock_type *s )
  1897. {
  1898.     if ( s->tcp.ip_type == TCP_PROTO ) {
  1899.     s->tcp.flags &= ~tcp_FlagPUSH;
  1900.     s->tcp.sock_mode |= TCP_LOCAL ;
  1901.     }
  1902. }
  1903. void sock_flush( sock_type *s )
  1904. {
  1905.     if ( s->tcp.ip_type == TCP_PROTO ) {
  1906.         s->tcp.sock_mode &= ~TCP_LOCAL;
  1907.     tcp_Flush( s );
  1908.     }
  1909. }
  1910.  
  1911. /*
  1912.  * sock_flushnext - cause next transmission to have a flush
  1913.  */
  1914. void sock_flushnext( sock_type *s)
  1915. {
  1916.     if (s->tcp.ip_type == TCP_PROTO ) {
  1917.         s->tcp.flags |= tcp_FlagPUSH;
  1918.         s->tcp.sock_mode &= ~TCP_LOCAL;
  1919.     }
  1920. }
  1921. /*
  1922.  * sock_putc - put a character
  1923.  *         - no expansion but flushes on '\n'
  1924.  *         - returns character
  1925.  */
  1926. byte sock_putc( sock_type *s, byte c )
  1927. {
  1928.     if (( c == '\n') || ( c == '\r'))
  1929.     sock_flushnext( s );
  1930.     sock_write( s, &c, 1 );
  1931.     return( c );
  1932. }
  1933.  
  1934. word sock_getc( sock_type *s )
  1935. {
  1936.     char ch;
  1937.     return( sock_read( s, &ch, 1 ) < 1 ? EOF : ch );
  1938. }
  1939.  
  1940. /*
  1941.  * sock_puts - does not append carriage return in binary mode
  1942.  *         - returns length
  1943.  */
  1944. sock_puts( sock_type *s, byte *dp )
  1945. {
  1946.     int len, oldmode;
  1947.  
  1948.     len = strlen( dp );
  1949.  
  1950.     if (s->tcp.sock_mode & TCP_MODE_ASCII ) {
  1951.         if (s->tcp.ip_type == TCP_PROTO )
  1952.             s->tcp.sock_mode |= TCP_LOCAL;
  1953.         sock_noflush( s );
  1954.         if (len) sock_write( s, dp, len );
  1955.         sock_flushnext( s );
  1956.         sock_write( s, "\r\n", 2 );
  1957.     } else {
  1958.         sock_flushnext( s );
  1959.         sock_write( s, dp, len );
  1960.     }
  1961.     return( len );
  1962. }
  1963.  
  1964. /*
  1965.  * sock_update - update the socket window size to the other guy
  1966.  */
  1967. static void sock_update( tcp_Socket *s )
  1968. {
  1969.     if (s->ip_type == TCP_PROTO) {
  1970.         if ( !s->rdatalen )
  1971.             tcp_send( s, __LINE__ );              /* update the window */
  1972.     else
  1973.         tcp_sendsoon( s );
  1974.     }
  1975. }
  1976. /*
  1977.  * sock_gets - read a string from any socket
  1978.  *         - return length of returned string
  1979.  *           - removes end of line terminator(s)
  1980.  *
  1981.  *           - Quentin Smart fixed some problems
  1982.  */
  1983. int sock_gets( sock_type *s, byte *dp, int n )
  1984. {
  1985.     int len, templen, *np;
  1986.     char *src_p, *temp, *temp2;
  1987.  
  1988.     if ( s->udp.ip_type == UDP_PROTO ) {
  1989.     src_p = s->udp.rdata;
  1990.     np = &s->udp.rdatalen;
  1991.     } else {
  1992.     src_p = s->tcp.rdata;
  1993.     np = &s->tcp.rdatalen;
  1994.     }
  1995.     if ( *np == 0 ) return( 0 );
  1996.  
  1997.     // eat trailing \n or \0 from previous line
  1998.     if ( *src_p == 0 || *src_p == '\n' ) {
  1999.         movmem( src_p + 1, src_p, *np -= 1 );
  2000.         if ( !*np ) return( 0 );
  2001.     }
  2002.  
  2003.     if ( --n > *np ) n = *np;
  2004.  
  2005.     // Q.Smart found and fixed a bug here
  2006.     memcpy( dp, src_p, n );     // copy everything
  2007.     dp[ n ] = 0;                // terminate new string
  2008.     temp = memchr( dp, '\n', n);
  2009.     temp2= memchr( dp, '\r', n);
  2010.  
  2011.     if (temp)  *temp = 0;
  2012.     if (temp2) *temp2= 0;
  2013.  
  2014.     // skip if there were no crs
  2015.     if ( !temp2 ) {
  2016.         *dp = 0;
  2017.         return( 0 );
  2018.     }
  2019.  
  2020. //  not: len = strlen( dp );
  2021.     len = (int)(( temp ? min( FP_OFF(temp), FP_OFF(temp2)) :
  2022.         FP_OFF(temp2)) - FP_OFF(dp));
  2023.  
  2024.     // expect \r\n or \r\0 or \n or \r
  2025.     // so get first of the two
  2026.  
  2027.     if ( temp == NULL ) {       /* handles \r only */
  2028.         temp = temp2;
  2029.         temp2 = NULL;
  2030.     } else if ( FP_OFF( temp ) > FP_OFF( temp2 ))
  2031.         temp = temp2;           // handles trailing \n or \0
  2032.  
  2033.     n = len + 1;                // account for first \r
  2034.  
  2035.     // we check next char if it exists, and skip it if 0, \r, or \n
  2036.     if ((*np > n) && !src_p[n] ) n++;
  2037.     movmem( &src_p[ n ], src_p, *np -= n );
  2038.     if (*np < 0) *np = 0;
  2039.  
  2040.     sock_update( s );   /* new window */
  2041.     return( len );
  2042. }
  2043.  
  2044.  
  2045. /*
  2046.  * sock_dataready - returns number of bytes waiting to be ready
  2047.  *          - if in ASCII mode, return 0 until a line is present
  2048.  *            or the buffer is full
  2049.  */
  2050. word sock_dataready( sock_type *s )
  2051. {
  2052.     int len;
  2053.     char *p;
  2054.  
  2055.     if (!(len = s->tcp.rdatalen)) return( 0 );
  2056.  
  2057.     if ( s->tcp.sock_mode & TCP_MODE_ASCII ) {
  2058.         p = s->tcp.rdata;
  2059.         if ( *p == '\n' ) {
  2060.             movmem( p + 1, p, s->tcp.rdatalen = --len);
  2061.             if ( ! len ) return( 0 );
  2062.         }
  2063.         /* check for terminating \r */
  2064.         if ( memchr( p, '\r', len))
  2065.             return( len );
  2066.         return( 0 );
  2067.     } else
  2068.         return( len );
  2069. }
  2070.  
  2071. sock_established( sock_type *s )
  2072. {
  2073.     switch ( s->tcp.ip_type ) {
  2074.     case UDP_PROTO :
  2075.         return( 1 );
  2076.     case TCP_PROTO :
  2077.                 return( s->tcp.state == tcp_StateESTAB ||
  2078.                         s->tcp.state == tcp_StateESTCL ||
  2079.                         s->tcp.state == tcp_StateCLOSWT );
  2080.     default :
  2081.         return( 0 );
  2082.     }
  2083. }
  2084.  
  2085. sock_close( sock_type *s )
  2086. {
  2087.     switch (s->udp.ip_type) {
  2088.     case UDP_PROTO :
  2089.         udp_close( s );
  2090.         break;
  2091.     case TCP_PROTO :
  2092.         tcp_close( s );
  2093.         tcp_tick( s );
  2094.         break;
  2095.     }
  2096. }
  2097.  
  2098.  
  2099. /*
  2100.  * _ip_delay0 called by macro sock_wait_established()
  2101.  * _ip_delay1 called by macro sock_wait_intput()
  2102.  * _ip_delay2 called by macro sock_wait_closed();
  2103.  *
  2104.  */
  2105.  
  2106. _ip_delay0( s, timeoutseconds, fn, statusptr )
  2107. sock_type *s;
  2108. int timeoutseconds;
  2109. procref fn;
  2110. int *statusptr;
  2111. {
  2112.     int status;
  2113.     ip_timer_init( s , timeoutseconds );
  2114.     do {
  2115.     if ( s->tcp.ip_type == TCP_PROTO ) {
  2116.         if ( tcp_established( s )) {
  2117.         status = 0;
  2118.         break;
  2119.         }
  2120.     }
  2121.     kbhit();    /* permit ^c */
  2122.     if ( !tcp_tick( s )) {
  2123.              if (!s->tcp.err_msg) s->tcp.err_msg = "Host refused connection";
  2124.          status = -1;    /* get an early reset */
  2125.          break;
  2126.     }
  2127.     if ( ip_timer_expired( s )) {
  2128.             s->tcp.err_msg = "Open timed out";
  2129.             sock_close( s );
  2130.         status = -1;
  2131.         break;
  2132.     }
  2133.     if ( fn ) if (status = fn(s)) break;
  2134.     if ( s->tcp.usr_yield ) (*s->tcp.usr_yield)();
  2135.     if ( s->tcp.ip_type == UDP_PROTO ) {
  2136.         status = 0;
  2137.         break;
  2138.     }
  2139.     } while ( 1 );
  2140.     if (statusptr) *statusptr = status;
  2141.     return( status );
  2142. }
  2143.  
  2144. _ip_delay1( s, timeoutseconds, fn, statusptr)
  2145. sock_type *s;
  2146. int timeoutseconds;
  2147. procref fn;
  2148. int *statusptr;
  2149. {
  2150.     int status;
  2151.     ip_timer_init( s , timeoutseconds );
  2152.  
  2153.     sock_flush( s );    /* new enhancement */
  2154.  
  2155.     do {
  2156.     if ( sock_dataready( s )) {
  2157.         status = 0;
  2158.         break;
  2159.     }
  2160.     kbhit();    /* permit ^c */
  2161.  
  2162.     if ( !tcp_tick( s )) {
  2163.         status = 1;
  2164.         break;
  2165.     }
  2166.     if ( ip_timer_expired( s )) {
  2167.             s->tcp.err_msg = "Connection timed out";
  2168.             sock_close( s );
  2169.         status = -1;
  2170.         break;
  2171.     }
  2172.     if (fn) {
  2173.         if (status = fn(s))
  2174.         break;
  2175.     }
  2176.     if ( s->tcp.usr_yield ) (*s->tcp.usr_yield)();
  2177.     } while ( 1 );
  2178.     if (statusptr) *statusptr = status;
  2179.     return( status );
  2180. }
  2181.  
  2182. _ip_delay2( s, timeoutseconds, fn, statusptr)
  2183. sock_type *s;
  2184. int timeoutseconds;
  2185. procref fn;
  2186. int *statusptr;
  2187. {
  2188.     int status;
  2189.     ip_timer_init( s , timeoutseconds );
  2190.  
  2191.     if (s->tcp.ip_type != TCP_PROTO ) {
  2192.         if ( statusptr ) * statusptr = 1;
  2193.         return( 1 );
  2194.     }
  2195.  
  2196.     do {
  2197.         /* in this situation we KNOW user not planning to read rdata */
  2198.         s->tcp.rdatalen = 0;
  2199.     kbhit();    /* permit ^c */
  2200.     if ( !tcp_tick( s )) {
  2201.         status = 1;
  2202.         break;
  2203.     }
  2204.     if ( ip_timer_expired( s )) {
  2205.             s->tcp.err_msg = "Connection timed out";
  2206.         sock_abort( s );
  2207.         status = -1;
  2208.         break;
  2209.     }
  2210.     if (fn) {
  2211.         if (status = fn(s))
  2212.         break;
  2213.     }
  2214.     if ( s->tcp.usr_yield ) (*s->tcp.usr_yield)();
  2215.  
  2216.     } while ( 1 );
  2217.     if (statusptr) *statusptr = status;
  2218.     return( status );
  2219. }
  2220.  
  2221.  
  2222. char *rip( char *s )
  2223. {
  2224.     char *temp;
  2225.  
  2226.     if (temp = (char *)strchr( s, '\n')) *temp = 0;
  2227.     if (temp = (char *)strchr( s, '\r')) *temp = 0;
  2228.     return( s );
  2229. }
  2230.  
  2231.                                  
  2232.